#pragma once
#include <iostream>
#include <string>
#include <memory.h>
#include <strings.h> // for bzero
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Log.hpp"
#include "Comm.hpp"
#include "InitAddr.hpp"
namespace SocketModule
{
	class Socket;
	using Sockptr = std::shared_ptr<SocketModule::Socket>;
	using namespace LogModule;
	// 基类，采用模板方法模式
	class Socket
	{
	public:
		~Socket() = default;
		// 虚函数，由子类实现
		virtual void SocketCreate() = 0;						 // 创建套接字
		virtual bool SocketBind(int post) = 0;					 // 绑定地址 传入端口号
		virtual bool SocketListen() = 0;						 // 监听连接
		virtual int SocketAccept(Inetaddr *client_addr) = 0; // 接收连接
		virtual int Recv(std::string *out) = 0;					 // 读取数据
		virtual int Send(const std::string &in) = 0;			 // 发送数据
		virtual void SocketClose() = 0;							 // 关闭套接字
		virtual int Fd() = 0;							 // 返回套接字描述符
		//  // 提供一个创建listensockfd的固定讨论
		void BulidTcpserverMethod(int post)
		{
			SocketCreate();
			SocketBind(post);
			SocketListen();
		}

	private:
	};

	class TcpSocket : public Socket
	{
	public:
		TcpSocket() : _sockfd(gdefaultsockfd)
		{
		}
		TcpSocket(int sockfd) : _sockfd(sockfd)
		{
		}
		virtual ~TcpSocket()
		{
		}
		virtual void SocketCreate() override // 创建套接字
		{
			_sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
			if (_sockfd < 0)
			{
				LOG(LogLevel::ERROR) << "create socket failed";
				exit(SOCKET_ERR);
			}
			LOG(LogLevel::DEBUG) << "create socket success";
		}
		virtual bool SocketBind(int post) override // 绑定地址 传入端口号
		{
			if (_sockfd == gdefaultsockfd)
			{
				LOG(LogLevel::ERROR) << "socket not create";
				return false;
			}
			Inetaddr addr(post);
			int ret = bind(_sockfd, addr.Netaddr(), addr.NetaddrLen());
			if (ret < 0)
			{
				LOG(LogLevel::ERROR) << "bind socket failed";
				exit(BIND_ERR);
			}
			LOG(LogLevel::DEBUG) << "bind socket success";
			return true;
		}
		virtual bool SocketListen() override // 监听连接
		{
			if (_sockfd == gdefaultsockfd)
			{
				return false;
			}
			int ret = listen(_sockfd, gbacklog);
			if (ret < 0)
			{
				LOG(LogLevel::ERROR) << "listen socket failed";
				exit(LISTEN_ERR);
			}
			LOG(LogLevel::DEBUG) << "listen socket success";
			return true;
		}
		// 传客户端信息
		virtual int SocketAccept(Inetaddr *client_addr) override // 接收连接
		{
			if (!client_addr) // 传空指针
			{
				LOG(LogLevel::ERROR) << "client_addr is null";
				return -1;
			}
			struct sockaddr_in pree;
			socklen_t len = sizeof(pree);
			int newsockfd = accept(_sockfd, CONV(&pree), &len);
			if (newsockfd < 0)
			{
				LOG(LogLevel::ERROR) << "accept socket failed";
				return -1;
			}
			LOG(LogLevel::DEBUG) << "accept socket success";
			client_addr->setaddr(pree, len);
			return newsockfd;
		}
		virtual int Recv(std::string *out) override // 读取数据
		{
			char buffer[1024 * 8];
			auto size = recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
			if (size > 0)
			{
				buffer[size] = 0;
				*out = buffer;
			}
			return size;
		}
		virtual int Send(const std::string &in) override // 发送数据
		{
			auto size = send(_sockfd, in.c_str(), in.size(), 0);
			return size;
		}
		virtual void SocketClose() override // 关闭套接字
		{
			if (_sockfd == gdefaultsockfd)
			{
				return;
			}
			close(_sockfd);
			LOG(LogLevel::DEBUG) << "close socket success";
		}
		virtual int Fd() override
		{
			return _sockfd;
		}

	private:
		int _sockfd;
	};
}
